﻿/*
 * This file is part of MonoStrategy.
 *
 * Copyright (C) 2010-2011 Christoph Husse
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors: 
 *      # Christoph Husse
 * 
 * Also checkout our homepage: http://monostrategy.codeplex.com/
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace MonoStrategy
{
    public delegate void Procedure();
    public delegate void Procedure<T>(T inParam);
    public delegate void Procedure<T1, T2>(T1 inParam1, T2 inParam2);

    public enum Direction : int
    {
       // _000,
        _045,
        _090,
        _135,
        //_180,
        _225,
        _270,
        _315,

        // must be the last element!
        Count
    }

    internal static class DirectionUtils
    {
        internal const Int32 DirCount = 8;

        internal static Direction? GetWalkingDirection(Point inFrom, Point inTo)
        {
            return GetWalkingDirection(new Point(inTo.X - inFrom.X, inTo.Y - inFrom.Y));
        }

        internal static Direction? GetNearestWalkingDirection(Point inNormedDiff)
        {
            if (inNormedDiff.X == 0)
            {
                if (inNormedDiff.Y == -1) return Direction._045;
                else if (inNormedDiff.Y == 1) return Direction._225;
                else 
                    return null;
            }
            else if (inNormedDiff.X == 1)
            {
                if (inNormedDiff.Y == -1) return Direction._045;
                else if (inNormedDiff.Y == 0) return Direction._090;
                else if (inNormedDiff.Y == 1) return Direction._135;
                else return null;
            }
            else if (inNormedDiff.X == -1)
            {
                if (inNormedDiff.Y == -1) return Direction._315;
                else if (inNormedDiff.Y == 0) return Direction._270;
                else if (inNormedDiff.Y == 1) return Direction._225;
                else return null;
            }
            else return null;
        }

        internal static Direction? GetWalkingDirection(Point inNormedDiff)
        {
            if (inNormedDiff.X == 0)
            {
                //if (diffY == -1) return Direction._000;
                //else if (diffY == 1) return Direction._180;
                //else 
                return null;
            }
            else if (inNormedDiff.X == 1)
            {
                if (inNormedDiff.Y == -1) return Direction._045;
                else if (inNormedDiff.Y == 0) return Direction._090;
                else if (inNormedDiff.Y == 1) return Direction._135;
                else return null;
            }
            else if (inNormedDiff.X == -1)
            {
                if (inNormedDiff.Y == -1) return Direction._315;
                else if (inNormedDiff.Y == 0) return Direction._270;
                else if (inNormedDiff.Y == 1) return Direction._225;
                else return null;
            }
            else return null;
        }

        internal static Point GetDirectionVector(Direction inDirection)
        {
            Point result;

            switch (inDirection)
            {
                //case Direction._000: result = new Point(0, -1); break;
                case Direction._045: result = new Point(1, -1); break;
                case Direction._090: result = new Point(1, 0); break;
                case Direction._135: result = new Point(1, 1); break;
                //case Direction._180: result = new Point(0, 1); break;
                case Direction._225: result = new Point(-1, 1); break;
                case Direction._270: result = new Point(-1, 0); break;
                case Direction._315: result = new Point(-1, -1); break;
                default:
                    throw new ArgumentException();
            }

            return result;
        }
    }
}
